<?php

namespace App\Models;

use App\Models\News\Notification;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Facades\DB;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Authenticatable implements JWTSubject
{
    use Notifiable;
    use SoftDeletes;

    protected $dates = ['deleted_at'];  //开启软删除
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'id','pid', 'mobile', 'nickname', 'group_id', 'account', 'password', 'avatar', 'status', 'remark', 'register_ip', 'client_id'
    ];

    protected $appends = ['name_str','card_no_str'];
    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password','pay_password'
    ];

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }


    public function getJWTCustomClaims()
    {
        return [];
    }

    /**
     * 用户名称星号处理
     */
    public function getNameStrAttribute(){
        if (!isset($this->attributes['name']) || empty($this->attributes['name'])) {
            return '';
        }
        $name = $this->attributes['name'];
        $string = starReplace($name);
        return $string;
    }

    /**
     * 卡号星号处理
     */
    public function getCardNoStrAttribute(){
        if (!isset($this->attributes['card_no']) || empty($this->attributes['card_no'])) {
            return '';
        }

        $card_no = $this->attributes['card_no'];
        if (strlen($card_no) > 5) {
            $string = hideStr($card_no, -1, 4,4);
        }else{
            $string = $card_no;
        }
        return $string;
    }

    /**
     * 获取用户消息列表
     */
    public function notifications ()
    {
        return $this->hasMany(Notification::class, 'notifiable_id', 'id')
            ->where('type','App\Notifications\UserNotification')
            ->orderBy('created_at', 'desc');
    }

    /**
     * 获取用户已读消息
     */
    public function unreadNotifications ()
    {
        return $this->hasMany(Notification::class, 'notifiable_id', 'id')->orderBy('created_at', 'desc')
            ->where('type','App\Notifications\UserNotification')
            ->whereNotNull('read_at');
    }

    /**
     * 获取用户未读读消息
     */
    public function readNotifications ()
    {
        return $this->hasMany(Notification::class, 'notifiable_id', 'id')->orderBy('created_at', 'desc')
            ->where('type','App\Notifications\UserNotification')
            ->whereNull('read_at');
    }

    /**
     * 功能:条件查询
     * @param array $param
     * @return array
     */
    static public function listByWhere($param = [])
    {
        /*条件初始化*/
        $where = isset($param['where']) ? $param['where'] : [];
        $whereIn = isset($param['whereIn']) ? $param['whereIn'] : [];
        $orderBy = isset($param['orderBy']) ? $param['orderBy'] : ['id desc'];
        $groupBy = isset($param['groupBy']) ? $param['groupBy'] : [];
        $field = isset($param['field']) ? $param['field'] : ['*'];
        $with = isset($param['with']) ? $param['with'] : [];
        $whereHas = isset($param['whereHas']) ? $param['whereHas'] : [];
        $whereNull = isset($param['whereNull']) ? $param['whereNull'] : [];
        $whereNotNull = isset($param['whereNotNull']) ? $param['whereNotNull'] : [];
        array_key_exists('limit', $param) OR $param['limit'] = config('rhzc.pageSize');
        /*开始查询*/
        $res = self::select($field)
            ->where($where)
            /*in查询*/
            ->when($whereIn, function ($query) use ($whereIn) {
                foreach ($whereIn as $k => $v) {
                    $query->whereIn($v[0], $v[1]);
                }
            })
            /*连表查询*/
            ->when($whereHas, function ($query) use ($whereHas) {
                foreach ($whereHas as $k => $v) {
                    $query->whereHas($v[0], $v[1]);
                }
            })
            /* 为空查询*/
            ->when($whereNull, function ($query) use($whereNull) {
                foreach ($whereNull as $k=>$v) {
                    $query->whereNull($v);
                }
            })
            /* 非空查询*/
            ->when($whereNotNull, function ($query) use($whereNotNull) {
                foreach ($whereNotNull as $k=>$v) {
                    $query->whereNotNull($v);
                }
            })
            /*关联查询*/
            ->when($with, function ($query) use ($with) {
                foreach ($with as $k => $v) {
                    $query->with($v);
                }
            })
            /*排序*/
            ->when($orderBy, function ($query) use ($orderBy) {
                foreach ($orderBy as $k => $v) {
                    $demo = explode(' ', $v);
                    $query->orderBy($demo[0], $demo[1]);
                }
            })
            /*分组*/
            ->when($groupBy, function ($query) use ($groupBy) {
                $query->groupBy($groupBy);
            })
            ->paginate($param['limit'])
            ->toArray();
        return ['total' => $res['total'], 'list' => $res['data']];
    }

    /**
     * 查询所有
     * @param array $param
     * @return mixed
     */
    static public function getAll($param = [])
    {
        /*条件初始化*/
        $where = isset($param['where']) ? $param['where'] : [];
        $whereIn = isset($param['whereIn']) ? $param['whereIn'] : [];
        $orderBy = isset($param['orderBy']) ? $param['orderBy'] : ['id desc'];
        $groupBy = isset($param['groupBy']) ? $param['groupBy'] : [];
        $field = isset($param['field']) ? $param['field'] : ['*'];
        $with = isset($param['with']) ? $param['with'] : [];
        $whereHas = isset($param['whereHas']) ? $param['whereHas'] : [];
        $whereBetween = isset($param['whereBetween']) ? $param['whereBetween'] : [];
        $whereNull = isset($param['whereNull']) ? $param['whereNull'] : [];
        $whereNotNull = isset($param['whereNotNull']) ? $param['whereNotNull'] : [];
        array_key_exists('pageSize', $param) OR $param['pageSize'] = config('admin.pageSize');
        /*开始查询*/
        $res = self::select($field)
            ->where($where)
            /*in查询*/
            ->when($whereIn, function ($query) use ($whereIn) {
                foreach ($whereIn as $k => $v) {
                    $query->whereIn($v[0], $v[1]);
                }
            })
            ->when($whereBetween, function ($query) use ($whereBetween) {
                foreach ($whereBetween as $k => $v) {
                    $query->whereBetween($v[0], $v[1]);
                }
            })
            /*关联查询*/
            ->when($with, function ($query) use ($with) {
                foreach ($with as $k => $v) {
                    $query->with($v);
                }
            })
            /*连表查询*/
            ->when($whereHas, function ($query) use ($whereHas) {
                foreach ($whereHas as $k => $v) {
                    $query->whereHas($v[0], $v[1]);
                }
            })
            /* 为空查询*/
            ->when($whereNull, function ($query) use($whereNull) {
                foreach ($whereNull as $k=>$v) {
                    $query->whereNull($v);
                }
            })
            /* 非空查询*/
            ->when($whereNotNull, function ($query) use($whereNotNull) {
                foreach ($whereNotNull as $k=>$v) {
                    $query->whereNotNull($v);
                }
            })
            /*排序*/
            ->when($orderBy, function ($query) use ($orderBy) {
                foreach ($orderBy as $k => $v) {
                    $demo = explode(' ', $v);
                    $query->orderBy($demo[0], $demo[1]);
                }
            })
            /*分组*/
            ->when($groupBy, function ($query) use ($groupBy) {
                $query->groupBy($groupBy);
            })
            ->get();
        return $res;
    }


    /**
     * 自增
     * @param $where 条件
     * @param $field 字段
     * @param int $num 步长
     * @return mixed
     */
    public static function incField($where,$field,$num=1){
        return self::where($where)->increment($field,$num);
    }

    /**
     * 自减
     * @param $where 条件
     * @param $field 字段
     * @param int $num 步长
     * @return mixed
     */
    public static function decField($where,$field,$num=1){
        return self::where($where)->decrement($field,$num);
    }

    /**
     * 用户登录记录模型
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     * User: john_chu
     * Email: john1668@qq.com
     */
    public function loginLog()
    {
        return $this->hasMany(UserLoginLog::class, 'user_id', 'id');
    }

    /**
     * 用户最后登录信息
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     * User: john_chu
     * Email: john1668@qq.com
     */
    public function lastLogin()
    {
        return $this->loginLog()->orderBy('time', 'Desc');
    }

    //以下都是修改器
    /**
     * 客服端ID
     * @param $value
     */
    public function setClientIdAttribute($value)
    {
        $this->attributes['client_id'] = json_encode($value);
    }

    /**
     * 客服端ID
     * @param $value
     * @return string
     */
    public function getClientIdAttribute($value)
    {
        return json_decode($value, true);
    }

    /**
     * 注册ip
     * @param $value
     */
    public function setRegisterIpAttribute($value)
    {
        $this->attributes['register_ip'] = sprintf("%u", ip2long($value));
    }

    /**
     * 获取注册ip
     * @param $value
     * @return string
     */
    public function getRegisterIpAttribute($value)
    {
        return !empty($value) ? long2ip(intval($value)) : '';
    }

    /**
     * 微信
     */
    public function weixin(){
        return $this->hasOne(UserWeixin::class,'user_id','id');
    }

    /**
     * 用户头像
     */
    public function file(){
        return $this->hasOne(File::class,'id','avatar');
    }

    /**
     * 详情
     * @param array $where
     * @return mixed
     */
    static function detail($where=array()){
        return self::where($where)->first();
    }

    /**
     * 更新内容
     * @param array $where 条件
     * @param array $field 更新字段
     * @return mixed
     */
    static public function modify($where=array(),$field=array()){
        return self::where($where)->update($field);
    }

    /**
     * 计算指定时间用户数量
     * @param $start_time 开始时间
     * @param $end_time 结束时间
     * @return mixed
     */
    static function statisticsByTime($start_time,$end_time){
        return self::whereBetween('created_at', [$start_time, $end_time])->count();
    }
}
